
package gui;


import java.awt.BorderLayout;
import java.awt.Component;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.Calendar;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import javax.swing.Box;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
import javax.swing.JTextField;

import urbanparks.Job;
import urbanparks.Park;
import urbanparks.User;
import urbanparks.UserSet;

/**
 * The main page for the GUI that controls most of the
 * visual aspects dealing with the execution of the user
 * stories from the point of view of the user.
 * 
 * @author Michelle Miller
 * @version Winter 2012
 */
@SuppressWarnings("serial")
public class MainPagePanel extends JPanel {

  /**
   * A reference to the controller class.
   */
  private final UrbanParksManagerFrame my_manager;

  /**
   * A reference to the panel that displays the jobs on a
   * visual calendar format.
   */
  private CalendarPanel my_calendar_panel;

  /**
   * A reference to the panel that contains all of the
   * navigation controls.
   */
  private NavigationPanel my_nav_panel;

  /**
   * Constructor for the MainPagePanel that sets up the
   * calendar panel and the navigation panel.
   * 
   * @param the_manager A reference to the manager of this
   *          instance.
   */
  public MainPagePanel(
      final UrbanParksManagerFrame the_manager) {
    super(new BorderLayout());
    my_manager = the_manager;
    my_calendar_panel = new CalendarPanel(my_manager);
    my_nav_panel = new NavigationPanel();
    this.add(my_calendar_panel, BorderLayout.CENTER);
    this.add(my_nav_panel, BorderLayout.NORTH);
  }

  /**
   * The panel that contains all of the controls.
   * 
   * @author Michelle Miller
   * @version Winter 2012
   */
  private class NavigationPanel extends JPanel {

    /**
     * Constructor for the NavigationPanel.
     */
    public NavigationPanel() {
      super();
      final int permissions =
          my_manager.getCurrentUser().getPermissionLevel();
      if (permissions == UserSet.USER_VOLUNTEER) {
        initVolunteerNav();
      } else if (permissions == UserSet.USER_STAFF) { 
        initStaffNav();
      } else { //user is a park manager
        initParkManagerNav();
      }
    }

    /**
     * Add the correct components to the NavigationPanel
     * for if the user is a ParkManager.
     */
    private void initParkManagerNav() {
      this.add(getPreviousMonth());
      this.add(getNextMonth());
      this.add(getPendingJobs());
      this.add(getAddJob());
      this.add(getSignOut());

    }

    /**
     * Add the correct components to the NavigationPanel
     * for if the user is a StaffMember.
     */
    private void initStaffNav() {
      this.add(getPreviousMonth());
      this.add(getNextMonth());
      this.add(getBlackballed());
      this.add(getSignOut());
      this.add(getPendingLabel());

    }

    /**
     * Add the correct components to the NavigationPanel
     * for if the user is a Volunteer.
     */
    private void initVolunteerNav() {
      this.add(getPreviousMonth());
      this.add(getNextMonth());
      this.add(getPendingJobs());
      this.add(getBrowseJobs());
      this.add(getSignOut());

    }

    /**
     * Returns a JPanel displaying the number of currently
     * pending jobs.
     * 
     * @return A JPanel displaying the number of currently
     *  pending jobs.
     */
    private JPanel getPendingLabel() {
      final JPanel pendingLabel =
          new JPanel(new BorderLayout());
      pendingLabel.add(new JLabel(
          "<html>Pending<br><center>Jobs</center></html>"),
          BorderLayout.WEST);
      pendingLabel.add(new JLabel(" : " +
          my_manager.getJobSet().getUpcomingJobs().size()),
          BorderLayout.EAST);
      return pendingLabel;
    }

    /**
     * Returns a JButton associated with the add new job
     * action. Opens a new AddJobForm.
     * 
     * @return A JButton associated with the add new job
     * action.
     */
    private JButton getAddJob() {
      final JButton addButton = new JButton("Add New Job");
      addButton.addActionListener(new ActionListener() {
        public void actionPerformed(
            final ActionEvent the_e) {
          final AddJob display = new AddJob();
          display.setVisible(true);
        }
      });
      return addButton;
    }

    /**
     * Returns a button that is associated with the action
     * of displaying a list of the currently blackballed
     * volunteers.
     * 
     * @return JButton that displays a dialog with a list
     *  of the currently blackballed volunteers
     */
    private JButton getBlackballed() {
      final JButton blackBall =
          new JButton("View Blackballed Volunteers");
      blackBall.addActionListener(new ActionListener() {
        public void actionPerformed(
            final ActionEvent the_e) {
          final BlackballedVolunteers display =
              new BlackballedVolunteers();
          display.setVisible(true);
        }
      });
      return blackBall;
    }

    /**
     * Returns a button that is associated with the action
     * of displaying a dialog that lets the user browse
     * through currently pending jobs.
     * 
     * @return JButton that displays a dialog to browse
     *  pending jobs.
     */
    private JButton getBrowseJobs() {
      final JButton browseButton =
          new JButton("Browse Jobs");
      browseButton.addActionListener(new ActionListener() {
        public void actionPerformed(
            final ActionEvent the_e) {
          final BrowseJobs display = new BrowseJobs();
          display.setVisible(true);
        }
      });
      return browseButton;
    }

    /**
     * Returns a button that is associated with the action
     * of updating the calendar panel to the next month.
     * 
     * @return JButton that updates the calendar panel to
     *  the next month.
     */
    private JButton getNextMonth() {
      final JButton nextButton = new JButton("Next Month");
      nextButton.addActionListener(new ActionListener() {
        public void actionPerformed(
            final ActionEvent the_e) {
          my_calendar_panel.nextMonth();
          my_manager.pack();
        }
      });
      return nextButton;
    }

    /**
     * Returns a button that is associated with the action
     * of displaying a dialog listing the pending jobs. If
     * the current user is a volunteer then this displays
     * the list of jobs that the user is volunteered for.
     * If the current user is a ParkManager, then this
     * displays a list of the pending jobs occurring in 
     * parks managed by the current user.
     * 
     * @return JButton that displays the pending jobs
     *  dialog.
     */
    private JButton getPendingJobs() {
      final JButton pendingButton =
          new JButton("View Pending Jobs");
      pendingButton.addActionListener(
          new ActionListener() {
            public void actionPerformed(
                final ActionEvent the_e) {
              final User u = my_manager.getCurrentUser();
              List<Job> jobs = null;
              if (u.getPermissionLevel() ==
                  UserSet.USER_VOLUNTEER) {
                jobs = my_manager.getJobSet().
                    getJobsByVolunteer(u.getEmailAddress());
              } else {
                jobs = my_manager.getJobSet().
                    getJobsByParkManager(u.getEmailAddress());
              }
              final PendingJobs display = 
                  new PendingJobs(jobs);
              display.setVisible(true);
            }
          });
      return pendingButton;
    }

    /**
     * Returns a button that is associated with the action
     * of updating the calendar panel to the previous
     * month.
     * 
     * @return JButton that updates the calendar panel to
     *  the previous month.
     */
    private JButton getPreviousMonth() {
      final JButton previousButton = 
          new JButton("Previous Month");
      previousButton.addActionListener(
          new ActionListener() {
            public void actionPerformed(
                final ActionEvent the_e) {
              my_calendar_panel.previousMonth();
              my_manager.pack();
            }
          });
      return previousButton;
    }

    /**
     * Returns a button that is associated with the action
     * of signing out of the program.
     * 
     * @return JButton that signs the current user out of
     *  the system.
     */
    private JButton getSignOut() {
      final JButton signout = new JButton("Sign Out");
      signout.addActionListener(new ActionListener() {
        public void actionPerformed(
            final ActionEvent the_e) {
          my_manager.switchToLoginPage();
        }
      });
      return signout;
    }

    /**
     * The custom JDialog that lets a ParkManager add a new
     * job.
     * 
     * @author Michelle Miller
     * @version Winter 2012
     */
    private class AddJob extends JDialog {

      /**
       * A reference to the JPanel that contains all the
       * components displayed in this component.
       */
      private final JPanel my_form =
          new JPanel(new BorderLayout());

      /**
       * A reference to the JPanel that contains all the
       * field components.
       */
      private JPanel my_fields;

      /**
       * A reference to the JPanel that contains all the
       * button components.
       */
      private JPanel my_buttons;

      /** 
       * A reference to the comboBox that lists the
       * available parks.
       */
      private JComboBox my_parks;

      /**
       * A reference to the textArea that gets the job
       * description.
       */
      private JTextArea my_desc;

      /**
       * A reference to the textArea that gets the light
       * grade description.
       */
      private JTextArea my_light_desc;

      /**
       * A reference to the textArea that gets the medium
       * grade description.
       */
      private JTextArea my_med_desc;

      /**
       * A reference to the textArea that gets the heavy
       * grade description.
       */
      private JTextArea my_heavy_desc;

      /**
       * A reference to the textField that gets the number
       * of volunteers needed for light grade.
       */
      private JTextField my_light_max;

      /**
       * A reference to the textField that gets the number
       * of volunteers needed for medium grade.
       */
      private JTextField my_med_max;

      /**
       * A reference to the textField that gets the number
       * of volunteers needed for heavy grade.
       */
      private JTextField my_heavy_max;

      /**
       * The JComboBox that lists the days of the month
       * currently selected.
       */
      private JComboBox my_day_cb = new JComboBox();

      /**
       * The JComboBox that lists the months to select
       * from.
       */
      private JComboBox my_month_cb;

      /**
       * The JComboBox that lists the years to select
       * from.
       */
      private JComboBox my_year_cb;

      /**
       * The JComboBox that lists the days from the job to
       * last to select from.
       */
      private JComboBox my_job_dur;

      /**
       * Constructor for the AddJobDialog, this does not
       * make the dialog visible.
       */
      public AddJob() {
        super(my_manager, "Add New Job");
        initializeForm();
        this.setContentPane(my_form);
        this.pack();
      }

      /**
       * Sets up the form with fields panel and the button
       * panel.
       */
      private void initializeForm() {
        my_fields = getFieldsPanel();
        my_buttons = getButtonPanel();
        my_form.add(my_fields, BorderLayout.CENTER);
        my_form.add(my_buttons, BorderLayout.SOUTH);
      }

      /**
       * Returns a JPanel containing all of the fields to
       * display.
       * 
       * @return JPanel containing all of the fields to
       * display.
       */
      private JPanel getFieldsPanel() {
        final JPanel fieldsPanel = new JPanel();
        fieldsPanel.setLayout(new BoxLayout(fieldsPanel,
            BoxLayout.Y_AXIS));
        my_parks = getParkCB();
        addFieldPanel("The Job Location :", my_parks,
            fieldsPanel);
        my_desc = getTextArea();
        JScrollPane scrollPaneDesc =
            new JScrollPane(my_desc);
        addFieldPanel("The Job Description :",
            scrollPaneDesc, fieldsPanel);

        my_light_desc = getTextArea();
        JScrollPane scrollPaneLow =
            new JScrollPane(my_light_desc);
        addFieldPanel("The Description for light duty :",
            scrollPaneLow, fieldsPanel);

        my_light_max = getTextBox();
        addFieldPanel(
            "The Volunteers needed for light duty :",
            my_light_max, fieldsPanel);

        my_med_desc = getTextArea();
        JScrollPane scrollPaneMed =
            new JScrollPane(my_med_desc);
        addFieldPanel("The Description for medium duty :",
            scrollPaneMed, fieldsPanel);

        my_med_max = getTextBox();
        addFieldPanel(
            "The Volunteers needed for medium duty :",
            my_med_max, fieldsPanel);

        my_heavy_desc = getTextArea();
        JScrollPane scrollPaneHigh =
            new JScrollPane(my_heavy_desc);
        addFieldPanel("The Description for heavy duty :",
            scrollPaneHigh, fieldsPanel);

        my_heavy_max = getTextBox();
        addFieldPanel(
            "The Volunteers needed for heavy duty :",
            my_heavy_max, fieldsPanel);

        my_month_cb = getMonthCB();
        my_year_cb = getYearCB();
        final JPanel datePanel = getDatePanel();
        fieldsPanel.add(datePanel);

        my_job_dur = getJobDurCB();
        addFieldPanel("The duration of the job in days :",
            my_job_dur, fieldsPanel);

        return fieldsPanel;
      }

      /**
       * Returns the ComboBox displaying the options for
       * job length in days.
       * 
       * @return The ComboBox displaying the options for
       *  job length.
       */
      private JComboBox getJobDurCB() {
        final Integer[] days = {1, 2};
        final JComboBox job_dur = new JComboBox(days);
        job_dur.setSelectedIndex(0);
        return job_dur;
      }

      /**
       * Returns a JPanel containing the Job Date Options
       * and the associated labels.
       * 
       * @return A JPanel containing the job date
       *  comboBoxes and labels.
       */
      private JPanel getDatePanel() {
        final JPanel datePanel = new JPanel();
        datePanel.setLayout(new BoxLayout(datePanel,
            BoxLayout.LINE_AXIS));
        datePanel.add(new JLabel("Month : "));
        datePanel.add(my_month_cb);
        datePanel.add(Box.createRigidArea(
            new Dimension(10, 0)));
        datePanel.add(new JLabel("Day : "));
        datePanel.add(my_day_cb);
        datePanel.add(Box.createRigidArea(
            new Dimension(10, 0)));
        datePanel.add(new JLabel("Year : "));
        datePanel.add(my_year_cb);

        datePanel.setAlignmentX(Component.LEFT_ALIGNMENT);
        return datePanel;
      }

      /**
       * Creates a panel that contains the provided label,
       * and component and adds it to the provided JPanel.
       * 
       * @param the_label The label to add to the new
       *  panel.
       * @param the_component The component to add to the
       *  new panel.
       * @param the_container The JPanel to add the new
       *  panel to.
       */
      private void addFieldPanel(String the_label,
          Component the_component, JPanel the_container) {
        final JPanel fields = new JPanel();

        final JLabel label = new JLabel(the_label);
        label.setAlignmentX(Component.LEFT_ALIGNMENT);
        fields.add(label);

        fields.add(the_component);

        fields.setAlignmentX(Component.LEFT_ALIGNMENT);
        the_container.add(fields);

      }

      /**
       * Returns a ComboBox listing the current year and
       * the year after.
       * 
       * @return A year selection comboBox.
       */
      private JComboBox getYearCB() {
        final Calendar date = Calendar.getInstance();
        final Integer[] years = {date.get(Calendar.YEAR),
            date.get(Calendar.YEAR) + 1};
        final JComboBox combo = new JComboBox(years);
        combo.setSelectedIndex(0);
        return combo;
      }

      /**
       * Returns a ComboBox listing the numerical months of
       * the year. Selection of a month triggers updating
       * of the day comboBox.
       * 
       * @return A month selection comboBox.
       */
      private JComboBox getMonthCB() {
        final Integer[] months =
          {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12};
        final JComboBox combo = new JComboBox(months);
        combo.setSelectedIndex(0);
        changeDayCB(1);
        combo.addActionListener (new ActionListener () {
          public void actionPerformed(ActionEvent e) {
            int month = (Integer) combo.getSelectedItem();
            changeDayCB(month);
          }

        });
        return combo;
      }

      /**
       * Updates the day comboBox to list the days in the
       * provided month.
       * 
       * @param the_month The month to populate the day
       *  list from.
       */
      protected void changeDayCB(final int the_month) {
        my_day_cb.removeAllItems();

        final Calendar date = Calendar.getInstance();
        date.set(Calendar.MONTH, the_month - 1);
        for (int i = 1; i <= date.getActualMaximum(
            Calendar.DAY_OF_MONTH); i++) {
          my_day_cb.addItem(i);
        }
        my_day_cb.setSelectedIndex(0);
      }

      /**
       * Returns a textField of size 5.
       * 
       * @return A textField of size 5.
       */
      private JTextField getTextBox() {
        final JTextField result = new JTextField(5);
        return result;
      }

      /**
       * Returns a sized textArea that has line wrap and
       * is editable.
       * 
       * @return A sized textArea that has line wrap and
       *  is editable.
       */
      private JTextArea getTextArea() {
        final JTextArea text = new JTextArea(4, 30);
        text.setEditable(true);
        text.setLineWrap(true);
        return text;
      }

      /**
       * Returns a ComboBox listing the parks managed by
       * the current user.
       * 
       * @return A ComboBox listing the parks managed by
       *  the current user.
       */
      private JComboBox getParkCB() {
        final List<Park> parks = my_manager.getParkSet().
            getParksManagedBy(my_manager.getCurrentUser().
                getEmailAddress());
        final String[] names = new String[parks.size()];
        for (int i = 0; i < names.length; i++) {
          names[i] = parks.get(i).getName();
        }
        final JComboBox combo = new JComboBox(names);
        combo.setSelectedIndex(0);
        return combo;
      }

      /**
       * Returns a JPanel that contains the buttons
       * displayed on this dialog.
       * 
       * @return JPanel containing the buttons to display.
       */
      private JPanel getButtonPanel() {
        final JPanel buttonPanel = new JPanel();
        buttonPanel.add(getAddJobButton());
        buttonPanel.add(makeCancelButton());
        return buttonPanel;
      }

      /**
       * Returns a button that is associated with the
       * action of adding the job.
       * 
       * @return JButton that adds the job.
       */
      private JButton getAddJobButton() {
        JButton result = new JButton("Add Job");
        result.addActionListener(new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            addJob();
          }
        });
        return result;
      }

      /**
       * Attempts to add the job to the jobSet and displays
       * an error dialog to the user if there was an error.
       */
      protected void addJob() {
        final String park =
            (String) my_parks.getSelectedItem();
        final String desc = my_desc.getText();
        final String ldesc = my_light_desc.getText();
        final String mdesc = my_med_desc.getText();
        final String hdesc = my_heavy_desc.getText();
        int lmax = 0;
        int mmax = 0;
        int hmax = 0;
        final int month =
            (Integer) my_month_cb.getSelectedItem();
        final int day =
            (Integer) my_day_cb.getSelectedItem();
        final int year =
            (Integer) my_year_cb.getSelectedItem();
        final int job_dur =
            (Integer) my_job_dur.getSelectedItem();
        boolean intsParsed = true;
        try {
          lmax = Integer.parseInt(my_light_max.getText());
          mmax = Integer.parseInt(my_med_max.getText());
          hmax = Integer.parseInt(my_heavy_max.getText());
        } catch (NumberFormatException e) {
          intsParsed = false;
        }
        if (desc.length() > 0 && ldesc.length() > 0 &&
            mdesc.length() > 0 && hdesc.length() > 0 &&
            intsParsed) {
          final Calendar date = Calendar.getInstance();
          date.set(Calendar.MONTH, month - 1);
          date.set(Calendar.DAY_OF_MONTH, day);
          date.set(Calendar.YEAR, year);
          date.get(Calendar.DATE);
          boolean added = my_manager.getJobSet().addJob(
              my_manager.getCurrentUser().
              getEmailAddress(), desc, park,
              my_manager.getCurrentUser().
              getEmailAddress(),
              ldesc, mdesc, hdesc,
              lmax, mmax, hmax,
              job_dur, date);
          if (added) {
            final String msg =
                "Your Job was succesfully added.";
            JOptionPane.showMessageDialog(my_manager, msg);
            MainPagePanel.this.my_calendar_panel.
              updateCalendar();
            my_manager.pack();
            AddJob.this.dispose();
          } else {
            final String msg =
                "<html>Your Job was not added due to con" +
                "flicts with the date or the allowed num" +
                "ber of jobs.<br><center>Please contact " + 
                "the office staff by phone or email." + 
                "</center></html>";
            JOptionPane.showMessageDialog(my_manager, msg);
          }


        } else {
          final String msg = "<html>Your Job was not add" +
              "ed because there were errors with the inf" + 
              "ormation provided.<br><center>Please chec" +
              "k the form and try again.</center></html>";
          JOptionPane.showMessageDialog(my_manager, msg);
        }
      }

      /**
       * Returns a button that is associated with the
       * action of closing the window.
       * 
       * @return JButton that closes the window without
       *  adding a job.
       */
      private JButton makeCancelButton() {
        JButton cancel = new JButton("Cancel");
        cancel.addActionListener(new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            AddJob.this.dispose();
          }
        });
        return cancel;
      }
    }

    /**
     * The custom JDialog that lets a Staff Member view a
     * list of the blackballed volunteers.
     * 
     * @author Michelle Miller
     * @version Winter 2012
     */
    private class BlackballedVolunteers extends JDialog {

      /**
       * Constructor for the BlackballedVolunteers dialog,
       * this does not make the dialog visible.
       */
      public BlackballedVolunteers() {
        super(my_manager, "View Blackballed Volunteers");
        final List<User> blackballedUsers = my_manager.
            getUserSet().getBlackballedVolunteers();
        final JPanel form = getForm(blackballedUsers);
        this.setContentPane(form);
        this.pack();
      }

      /**
       * Returns a JPanel that contains all of the
       * components to be displayed.
       * 
       * @param the_blackballed_users A list of the
       *  blackballed volunteers.
       * @return A JPanel that contains all of the
       *  components to be displayed.
       */
      private JPanel getForm(
          final List<User> the_blackballed_users) {
        final JPanel form = new JPanel(new BorderLayout());
        final JPanel list =
            getListPanel(the_blackballed_users);
        final JPanel buttons = getButtonPanel();
        form.add(list, BorderLayout.CENTER);
        form.add(buttons, BorderLayout.SOUTH);
        return form;
      }

      /**
       * Returns a JPanel that contains the buttons to
       * display.
       * 
       * @return A JPanel that contains the buttons to
       *  display.
       */
      private JPanel getButtonPanel() {
        final JPanel buttonPanel = new JPanel();
        buttonPanel.add(getCloseButton());
        return buttonPanel;
      }

      /**
       * Returns a button that is associated with the
       * action of closing the window.
       * 
       * @return JButton that closes the window without
       *  adding a job.
       */
      private JButton getCloseButton() {
        JButton close = new JButton("Close");
        close.addActionListener(new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            BlackballedVolunteers.this.dispose();
          }
        });
        return close;
      }   

      /**
       * Returns a JPanel that contains a list of the
       * blackballed volunteers or a message stating that
       * there are no blackballed volunteers to display.
       * 
       * @param the_blackballed_users A List of the
       *  blackballed volunteers to display.
       * @return A panel displaying the list of blackballed
       *  users.
       */
      private JPanel getListPanel(
          final List<User> the_blackballed_users) {
        final JPanel listPanel = new JPanel(new GridLayout(0, 1));
        if (the_blackballed_users == null) {
          listPanel.add(new JLabel("There are no " +
              "blackballed Volunteers to display."));
        } else {
          for (User u : the_blackballed_users) {
            listPanel.add(new JLabel(u.getFullName()));
          }
        }
        return listPanel;
      }
    }

    /**
     * The custom JDialog that lets the user browse through
     * the jobs with a variety of filtering options.
     * 
     * @author Michelle Miller
     * @version Winter 2012
     */
    private class BrowseJobs extends JDialog {

      /**
       * The main options for browsing pending jobs.
       */
      private final String[] my_main_options =
        {"Browse by Park", "Browse by Park District",
          "Browse by Region"};

      /**
       * The panel containing the Job to display.
       */
      private JPanel my_jobs_panel;

      /**
       * The combo box that displays the main browse
       * options.
       */
      private JComboBox my_main_cb;

      /**
       * The combo box that displays the secondary browse
       * options.
       */
      private JComboBox my_secondary_cb = new JComboBox();

      /**
       * The secondary options for if park is selected as
       * the main option.
       */
      private String[] my_parks;

      /**
       * The secondary options for if districts is selected
       * as the main option.
       */
      private String[] my_districts;

      /**
       * The secondary options for if regions is selected
       * as the main option.
       */
      private String[] my_regions;

      /**
       * The actionListener for populating the park
       * secondary options.
       */
      private final ActionListener my_parks_al =
          getParkAL();

      /**
       * The actionListener for populating the districts
       * secondary options.
       */
      private final ActionListener my_districts_al =
          getDistrictAL();

      /**
       * The actionListener for populating the regions
       * secondary options.
       */
      private final ActionListener my_regions_al =
          getRegionAL();

      /**
       * The JPanel that contains all the components to
       * display in this dialog.
       */
      private JPanel my_form;


      /**
       * Constructor for the BrowseJobs dialog, does not
       * set the element to visible.
       */
      public BrowseJobs() {
        super(my_manager, "Browse Jobs");
        initializeForm();
        this.setContentPane(my_form);
        this.pack();
      }

      /**
       * Initializes the form with the dropdown panel, the
       * jobs panel and the buttons panel.
       */
      private void initializeForm() {
        my_form = new JPanel(new BorderLayout());
        initializeMyParks();
        initializeMyDistricts();
        initializeMyRegions();
        final JPanel dropdowns = getDropDownPanel();
        final JPanel buttons = getButtonPanel();
        my_form.add(dropdowns, BorderLayout.NORTH);
        my_form.add(my_jobs_panel, BorderLayout.CENTER);
        my_form.add(buttons, BorderLayout.SOUTH);
      }

      /**
       * Initializes the my_parks field with the list of
       * parks.
       */
      private void initializeMyParks() {
        final List<Job> jobs =
            my_manager.getJobSet().getUpcomingJobs();
        final Set<String> parks = new HashSet<String>();
        for (Job j : jobs) {
          parks.add(j.getPark());
        }
        my_parks = parks.toArray(new String[parks.size()]);
      }

      /**
       * Initializes the my_districts field with the list
       * of districts.
       */
      private void initializeMyDistricts() {
        final List<Job> jobs =
            my_manager.getJobSet().getUpcomingJobs();
        final Set<String> district = new HashSet<String>();
        for (Job j : jobs) {
          district.add(my_manager.getParkSet().getPark(
              j.getPark()).getParkDistrict());
        }
        my_districts =
            district.toArray(new String[district.size()]);
      }

      /**
       * Initializes the my_regions field with the list of
       * cities.
       */
      private void initializeMyRegions() {
        final List<Job> jobs =
            my_manager.getJobSet().getUpcomingJobs();
        final Set<String> regions = new HashSet<String>();
        for (Job j : jobs) {
          regions.add(my_manager.getParkSet().getPark(
              j.getPark()).getCity());
        }
        my_regions =
            regions.toArray(new String[regions.size()]);
      }

      /**
       * Returns a JPanel containing the two dropdown menus
       * with options.
       * 
       * @return A JPanel containing the two dropdown menus
       *  with options.
       */
      private JPanel getDropDownPanel() {
        final JPanel ddPanel = new JPanel();
        my_main_cb = getMainComboBox();
        ddPanel.add(my_main_cb);
        ddPanel.add(my_secondary_cb);
        return ddPanel;
      }

      /**
       * Returns the Main comboBox.
       * 
       * @return The JComboBox with the main options.
       */
      private JComboBox getMainComboBox() {
        final JComboBox combo =
            new JComboBox(my_main_options);
        combo.setSelectedIndex(0);
        setSecondCB(my_parks, my_parks_al);
        combo.addActionListener (new ActionListener () {
          public void actionPerformed(ActionEvent e) {
            String str = (String)combo.getSelectedItem();
            if (str.equals(my_main_options[0])) {//by park
              setSecondCB(my_parks, my_parks_al);
            } else if (str.equals(my_main_options[1])) {
              //by park district
              setSecondCB(my_districts, my_districts_al);
            } else { //by region
              setSecondCB(my_regions, my_regions_al);
            }
          }

        });
        return combo;
      }

      /**
       * Sets the contents of the secondary comboBox to the
       * items in the_items and adds the provided
       * actionListener.
       * 
       * @param the_items The items to set as the contents
       *  of the secondary comboBox.
       * @param the_al The actionListener to add to the
       *  secondary comboBox.
       */
      protected void setSecondCB(String[] the_items,
          ActionListener the_al) {
        my_secondary_cb.removeAllItems();
        my_secondary_cb.removeActionListener(my_parks_al);
        my_secondary_cb.removeActionListener(
            my_districts_al);
        my_secondary_cb.removeActionListener(
            my_regions_al);
        for (String s : the_items) {
          my_secondary_cb.addItem(s);
        }
        my_secondary_cb.addActionListener(the_al);
        my_secondary_cb.setSelectedIndex(0);


      }

      /**
       * Returns the ActionListener that populates the job
       * panel with the jobs in the selected park.
       * 
       * @return A ActionListener that populates the job
       *  panel with the jobs in the selected park.
       */
      private ActionListener getParkAL() {
        return new ActionListener () {
          public void actionPerformed(ActionEvent e) {
            String parkName =
                (String) my_secondary_cb.getSelectedItem();
            updateJobsPanel(my_manager.getJobSet().
                getUpcomingJobsByPark(parkName));
          }
        };

      }

      /**
       * Returns the ActionListener that populates the job
       * panel with the jobs in the selected district.
       * 
       * @return A ActionListener that populates the job
       *  panel with the jobs in the selected district.
       */
      private ActionListener getDistrictAL() {
        return new ActionListener () {
          public void actionPerformed(ActionEvent e) {
            String districtName =
                (String) my_secondary_cb.getSelectedItem();
            updateJobsPanel(my_manager.getJobSet().
                getUpcomingJobsByDistrict(districtName,
                    my_manager.getParkSet()));
          }
        };
      }

      /**
       * Returns the ActionListener that populates the job
       * panel with the jobs in the selected city.
       * 
       * @return A ActionListener that populates the job
       * panel with the jobs in the selected city.
       */
      private ActionListener getRegionAL() {
        return new ActionListener () {
          public void actionPerformed(ActionEvent e) {
            String region =
                (String) my_secondary_cb.getSelectedItem();
            updateJobsPanel(my_manager.getJobSet().
                getUpcomingJobsByRegion(region,
                    my_manager.getParkSet()));
          }
        };
      }

      /**
       * Returns a JPanel containing the close button.
       * 
       * @return A JPanel containing the close button.
       */
      private JPanel getButtonPanel() {
        final JPanel buttonPanel = new JPanel();
        JButton closeButton = new JButton("Close");
        closeButton.addActionListener(
            new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            BrowseJobs.this.dispose();
          }
        });
        buttonPanel.add(closeButton);
        return buttonPanel;
      } 

      /**
       * Updates the panel that displays the list of jobs
       * to display the provided list of jobs.
       * 
       * @param the_jobs The list of jobs to display.
       */
      private void updateJobsPanel(
          final List<Job> the_jobs) {
        if (my_jobs_panel != null) {
          my_form.remove(my_jobs_panel);
        }
        my_jobs_panel =
            new JPanel(new GridLayout(the_jobs.size(), 1));
        if (the_jobs == null || the_jobs.size() == 0) {
          my_jobs_panel.add(new JLabel(
              "There are no jobs to display."));
        } else {
          for (Job j : the_jobs) {
            my_jobs_panel.add(getJobPanel(j));
          }
        }
        my_jobs_panel.repaint();
        my_form.add(my_jobs_panel, BorderLayout.CENTER);
        this.setMinimumSize(new Dimension(0, 0));
        this.pack();
        this.setMinimumSize(this.getSize());
      }

      /**
       * Returns A JPanel containing a button to the job
       * information and the job name and date.
       * 
       * @param the_job The job to add to the panel.
       * @return A panel containing the job information
       *  button and the job name and date.
       */
      private JPanel getJobPanel(final Job the_job) {
        final JPanel result = new JPanel();
        final JButton info = new JButton(
            "View Job Information");
        info.addActionListener(new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            final JobInformationForm display =
                new JobInformationForm(the_job, my_manager);
            display.setVisible(true);
          }
        });
        result.add(info);
        result.add(new JLabel(the_job.toParkDateString()));
        return result;
      }


    }

    /**
     * The custom JDialog that lets the user view their
     * pending jobs, for a volunteer this is the jobs that
     * they are signed up for, for a park manager this is
     * the jobs occurring at parks that they manage.
     * 
     * @author Michelle Miller
     * @version Winter 2012
     */
    private class PendingJobs extends JDialog {

      /**
       * Constructor for the PendingJobs dialog, does not
       * set the element to visible.
       * 
       * @param the_jobs A list of jobs to display in the
       *  dialog.
       */
      public PendingJobs(final List<Job> the_jobs) {
        super(my_manager, "View Pending Jobs");
        final JPanel form = getForm(the_jobs);
        this.setContentPane(form);
        this.pack();
        this.setMinimumSize(getSize());
      }

      /**
       * Returns a JPanel containing all of the components
       * displayed on this dialog.
       * 
       * @param the_jobs The list of jobs to display in 
       *  the dialog.
       * @return A JPanel containing all of the components
       *  displayed in this dialog.
       */
      private JPanel getForm(final List<Job> the_jobs) {
        final JPanel form = new JPanel(new BorderLayout());
        final JPanel list = getListPanel(the_jobs);
        final JPanel buttons = getButtonPanel();
        form.add(list, BorderLayout.CENTER);
        form.add(buttons, BorderLayout.SOUTH);
        return form;
      }

      /**
       * Returns a JPanel containing all of the buttons
       * displayed on this dialog.
       * 
       * @return A JPanel containing all of the buttons
       *  displayed in this dialog.
       */
      private JPanel getButtonPanel() {
        final JPanel buttonPanel = new JPanel();
        JButton closeButton = new JButton("Close");
        closeButton.addActionListener(
            new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            PendingJobs.this.dispose();
          }
        });
        buttonPanel.add(closeButton);
        return buttonPanel;
      }  

      /**
       * Returns a JPanel displaying the list of pending
       * jobs.
       * 
       * @param the_jobs The list of jobs to populate the
       *  JPanel with.
       * @return A JPanel displaying the list of pending
       *  jobs.
       */
      private JPanel getListPanel(
          final List<Job> the_jobs) {
        final JPanel result =
            new JPanel(new GridLayout(0, 1));
        if (the_jobs == null || the_jobs.size() == 0) {
          result.add(new JLabel(
              "There are no pending jobs to display."));
        } else {
          for (Job j : the_jobs) {
            result.add(getJobPanel(j));
          }
        }
        return result;
      }

      /**
       * Returns a JPanel displaying a single pending job
       * containing a job information button and a label
       * with the park name and date.
       * 
       * @param the_jobs The job to populate the JPanel
       *  with.
       * @return A JPanel displaying the job's park name
       *  and date and a button to the JobInformation Form.
       */
      private JPanel getJobPanel(final Job the_job) {
        final JPanel result = new JPanel();
        final JButton info =
            new JButton("View Job Information");
        info.addActionListener(new ActionListener() {
          public void actionPerformed(
              final ActionEvent the_e) {
            final JobInformationForm display =
                new JobInformationForm(the_job,
                     my_manager);
            display.setVisible(true);
          }
        });
        result.add(info);
        result.add(new JLabel(the_job.toParkDateString()));
        return result;
      }


    }
  }
}
